/* motor.c */
#include "motor.h"

typedef struct
{
    eTMR_Type * pwm_port;
    uint32_t    pwm_chn;
} pwm_chn_info_t;

#define BOARD_MOTORx_COUNT_MAX   4u
const pwm_chn_info_t pwm_chn_info_arr[BOARD_MOTORx_COUNT_MAX][2] =
{
    { {eTMR0, 4u}, {eTMR0, 5u} },
    { {eTMR0, 1u}, {eTMR0, 0u} }, /* reverse direction. */
    { {eTMR1, 0u}, {eTMR1, 1u} },
    { {eTMR0, 3u}, {eTMR0, 2u} }, /* reverse direction. */
};

volatile uint32_t motor_speed_val = 100u; /* 10%. */

#define BOARD_MOTORx_PWMx_ETMR_STEP_COUNT_MAX 1000  /* period 1khz. */

void motor_init(void)
{
    /* setup counter. */
    eTMR_CounterInit_Type etmr_init;

    etmr_init.ClkSrc = eTMR_CounterClkSrc_BusClk;
    etmr_init.ClkFreqHz = BOARD_MOTORx_PWMx_ETMR_CLK_SRC_HZ;
    etmr_init.StepFreqHz = 1000000u; /* 1mhz. */
    etmr_init.ModVal = BOARD_MOTORx_PWMx_ETMR_STEP_COUNT_MAX; /* 1khz for timeout. */
    etmr_init.EnableRunningOnDebug = false;
    etmr_init.EnableGlobalCountingBase = false;

    eTMR_InitCounter(eTMR0, &etmr_init);
    eTMR_InitCounter(eTMR1, &etmr_init);
    
    /* setup channel. */
    eTMR_ChannelOutputCompareInit_Type etmr_channel_init;
    
    etmr_channel_init.EnableComplementaryMode = false;
    etmr_channel_init.EnableDma = false;
    /* init. */
    etmr_channel_init.InitOutputLogic = eTMR_OutputLogic_Logic1;
    /* val0 would be used as the reset point. */
    etmr_channel_init.Val0 = 0;
    etmr_channel_init.OutputCompareEventForVal0 = eTMR_OutputCompareEvent_ToOutputLogic1;
    etmr_channel_init.EnableTriggerOutOnVal0 = false;
    /* val1 would be used to control the duty. */
    etmr_channel_init.Val1 = 0;
    etmr_channel_init.OutputCompareEventForVal1 = eTMR_OutputCompareEvent_ToOutputLogic0;
    etmr_channel_init.EnableTriggerOutOnVal1 = false;
    
    for (uint32_t i = 0u; i < BOARD_MOTORx_COUNT_MAX; i++)
    {
        eTMR_InitChannelOutputCompare(pwm_chn_info_arr[i][0].pwm_port, pwm_chn_info_arr[i][0].pwm_chn, &etmr_channel_init);
        eTMR_InitChannelOutputCompare(pwm_chn_info_arr[i][1].pwm_port, pwm_chn_info_arr[i][1].pwm_chn, &etmr_channel_init);
    }
    
    motor_update_all();
    
    eTMR_StartCounter(eTMR0);
    eTMR_StartCounter(eTMR1);
}

void motor_set_speed(uint32_t speed)
{
    if (speed > BOARD_MOTORx_PWMx_ETMR_STEP_COUNT_MAX)
    {
        speed = BOARD_MOTORx_PWMx_ETMR_STEP_COUNT_MAX;
    }
    motor_speed_val = speed;
}

uint32_t motor_get_speed(void)
{
    return motor_speed_val;
}

void motor_prepare_move(uint32_t id, motor_direction_t dir)
{
    if (dir == motor_direction_stop)
    {
        eTMR_UpdateChannelOutputCompareValue1(pwm_chn_info_arr[id][0].pwm_port, pwm_chn_info_arr[id][0].pwm_chn, 0u);
        eTMR_UpdateChannelOutputCompareValue1(pwm_chn_info_arr[id][1].pwm_port, pwm_chn_info_arr[id][1].pwm_chn, 0u);
    }
    else if (dir == motor_direction_forward)
    {
        eTMR_UpdateChannelOutputCompareValue1(pwm_chn_info_arr[id][0].pwm_port, pwm_chn_info_arr[id][0].pwm_chn, motor_speed_val);
        eTMR_UpdateChannelOutputCompareValue1(pwm_chn_info_arr[id][1].pwm_port, pwm_chn_info_arr[id][1].pwm_chn, 0u);
    }
    else /* motor_direction_backward. */
    {
        eTMR_UpdateChannelOutputCompareValue1(pwm_chn_info_arr[id][0].pwm_port, pwm_chn_info_arr[id][0].pwm_chn, 0u);
        eTMR_UpdateChannelOutputCompareValue1(pwm_chn_info_arr[id][1].pwm_port, pwm_chn_info_arr[id][1].pwm_chn, motor_speed_val);
    }
}

void motor_update_all(void)
{
    eTMR_DoLoadOk(eTMR0);
    eTMR_DoLoadOk(eTMR1);
}



/* EOF. */

